const fs = require('fs')
const { sqlite, database } = require("../JDBC");
const npk = require("./npk");
const { LOAD_STEP } = require("./npk");
const { rmAndmkdir } = require("../Common");
const { Task } = require("../Task");
const Path = require('path')
const windows = global.windows;

/** 
 * NPK模块封装接口
 * 只能在service端使用
*/

const init = () => {
    windows.setInitModule("NPK");
    console.log("NPK.init.js 检查数据库")

    //检查数据库
    sqlite.tableExist("npk_index").then(exist => {
        if (!exist) {
            let sqlPath = Path.join(__dirname, "default.sql")
            sqlite.doFile(sqlPath)
                .then(init) //再次执行
            return
        }
    });

    windows.setInitModuleSuccess("NPK");
}

const initIpcMain = () => {
    let ipcMain = require("electron").ipcMain;

    //ipcMain不能传递带方法的对象，只能带着token相互发消息了
    ipcMain.on("npk-event", (event, channel, token, ...data) => {
        if (Npk[channel]) {
            Npk[channel](token, ...data);
        } else {
            console.error("错误的channel", channel)
        }
    })
}

//建立缓存时枷锁，防止重复任务
let cache_lock = false;

const Npk = {

    /** npk文件非缓存处理 */

    //页面加载一个npk，获得所有img列表
    getNpkAll: (token, npkPath) => {
        console.log("getNpkAll");
        if (!npkPath) return;

        npk.openNpk(npkPath, LOAD_STEP.IMG).then(cursor => {

            console.log("getNpkAll", cursor.errors);
            console.log(cursor.imgIndexs.map(e => JSON.stringify(e).substring(1, 100)))

            let imgPaths = new Set();
            cursor.imgIndexs.forEach(imgIndex => {
                imgPaths.add(imgIndex.index_name);
            })

            windows.main.webContents.send("npk-reply", "getNpkAll", token, null, [...imgPaths]);

        }).catch(e => {
            console.error("getNpkAll error")
            console.error(e);
            windows.main.webContents.send("npk-reply", "getNpkAll", token, e, null);
        });

    },

    //页面加载一个npk，获得某个img下所有png预览图 base64
    //转出一个回传一个
    //消息体  data{code:int,text:string,index:int,base64:string}
    // code: 0: 立刻停止,text为原因
    // code: 1:返回base64图片,此时有index和base64属性
    // code: 2:错误消息，某个png解析失败
    // code: 3:指定任务数量，此时有count属性
    getNpkImgAll: (token, npkPath, imgPath) => {
        console.log("getNpkImgAll");
        if (!npkPath) return;
        if (!imgPath) return;

        //接收data后直接返回给页面
        npk.openNpkImgAll(npkPath, imgPath, (err, data) => {
            if (err) {
                console.error("openNpkImgAll callback error")
                console.error(err);
                windows.main.webContents.send("npk-reply", "getNpkImgAll", token, {
                    code: 0,
                    text: toString(err)
                });
                return
            }

            if (data && data.count) {
                windows.main.webContents.send("npk-reply", "getNpkImgAll", token, {
                    code: 3,
                    ...data
                })
            }

            if (data && data.error) {
                windows.main.webContents.send("npk-reply", "getNpkImgAll", token, {
                    code: 2,
                    text: data.error,
                    ...data
                })
            }

            if (data && data.base64) {
                windows.main.webContents.send("npk-reply", "getNpkImgAll", token, {
                    code: 1,
                    ...data
                });
            }

        })
    },

    getNpkImgIndex: (token, npkPath, imgPath, index) => {
        console.log("getNpkImgIndex");
        if (!npkPath) return;
        if (!imgPath) return;
        if (typeof (index) != "number") return;

        //接受data后直接返回给页面
        npk.openNpkImgIndex(npkPath, imgPath, index, (err, data) => {
            if (err) {
                console.error("openNpkImgAll callback error")
                console.error(err);
                windows.main.webContents.send("npk-reply", "getNpkImgIndex", token, err, null);
                return
            }

            windows.main.webContents.send("npk-reply", "getNpkImgIndex", token, null, data);
        })
    },

    //导出一个npk所有png文件
    //全部输出结束后返回信息
    exportNpkAll: (token, npkPath, dirPath) => {
        console.log("exportNpkAll");

        npk.openNpk(npkPath, LOAD_STEP.PNG).then(cursor => {

            //简单排个序
            // cursor.imgPngs.sort((e1, e2) => {
            //     if (e1.path != e2.path) {
            //         return e1.path.localeCompare(e2.path)
            //     }
            //     return e1.index - e2.index
            // })

            console.log("exportNpkAll接收结果", cursor.imgPngs.length, cursor.errors);
            // console.log(cursor.imgPngs.map(e => JSON.stringify(e).substring(1, 100)))

            new Promise((res, rej) => {
                rmAndmkdir(dirPath);
                let task = new Task(cursor.imgPngs.length, (result) => {
                    next(result);
                })

                cursor.imgPngs.forEach(pngs => {
                    let path = pngs.path.replaceAll("/", "_");
                    let npkDir = Path.basename(npkPath);
                    let outPath = Path.join(dirPath, npkDir, path, `${pngs.index}.png`);
                    // console.log("输出路径:", outPath);

                    pngs.png.writeAsync(outPath).then(t => {
                        task.push(true)

                    }).catch(e => {
                        console.error("输出png错误", `${outPath}`)
                        console.error(e)
                        cursor.errors.push(`输出png错误,${outPath},${e.toStirng()}`)
                        task.push(false);
                    })
                });

                const next = (result) => {
                    //统计输出信息
                    let success = 0;
                    let faild = cursor.imgIndexs.length - cursor.imgPngs.length; //imgIndex错误的个数

                    result.forEach(r => {
                        r ? success++ : faild++;
                    })

                    let outText = `导出完成！成功${success}个,失败${faild}个,错误日志:${cursor.errors.join("\n") || "无"}`
                    console.warn(outText)
                    res(outText);
                }

            }).then(result => {
                windows.main.webContents.send("npk-reply", "exportNpkAll", token, false, result);

            }).catch(e => {
                console.error("exportNpkAll")
                console.error(e);
                windows.main.webContents.send("npk-reply", "exportNpkAll", token, e, null);

            });

        }).catch(e => {
            console.error("exportNpkAll")
            console.error(e);
            windows.main.webContents.send("npk-reply", "exportNpkAll", token, e, null);
        });
    },

    //导出一个npk的某个img的所有png文件
    //@TODO
    exportNpkImgAll: (token, npkPath, imgPath, dirPath) => {

    },

    //导出一个npk的某个img的某个png文件
    //@TODO暂不实现
    exportNpkImgIndex: (token, npkPath, imgPath, index, dirPath) => {

    },

    /** imagePacks2缓存处理*/

    //设置imagePacks2文件夹，并建立缓存
    //返回消息参数 err,data:{code:,text}
    //   code: 0结束 1继续   text:string 消息
    cache_dirPath: (token, dirPath) => {
        //fs遍历文件夹 第一层的npk文件
        //循环调用openNp(路径，step.IMG)
        //结果都存入数据库
        console.log("cache_DirPath");

        if (cache_lock) {
            windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                code: 0,
                text: "正在执行一个建立缓存任务,请勿重复提交"
            });
            return
        }

        let startTime = new Date();
        cache_lock = true;

        if (!fs.existsSync(dirPath)) {
            windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                code: 0,
                text: "选定路径不存在"
            });
            cache_lock = false;
            return
        }

        let dirStat = fs.statSync(dirPath);
        if (!dirStat.isDirectory()) {
            windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                code: 0,
                text: "选定路径非文件夹"
            });

            cache_lock = false;
            return
        }

        let files = fs.readdirSync(dirPath)
            .filter(name => {
                return name.toLowerCase().indexOf(".npk") != -1;
            })
            .map(name => {
                return Path.join(dirPath, name);
            });

        //未发现npk文件 停止任务
        if (files.length <= 0) {
            cache_lock = false;
            windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                code: 0,
                text: '选定文件夹下未发现npk文件!',
            });
            return;
        }

        let task = new Task(files.length, rs => {
            next(rs)
        })

        //删掉数据库表重建
        let sqlPath = Path.join(__dirname, "default.sql");
        let sqlParams = [];
        sqlite.doFile(sqlPath).then(() => {
            files.forEach(npkPath => {
                npk.openNpk(npkPath, LOAD_STEP.START).then(cursor => {
                    // console.log("cache_DirPath", cursor.imgIndexs.length, cursor.errors);
                    // console.log(cursor.imgIndexs.map(e => JSON.stringify(e).substring(1, 100)))
                    cursor.npkIndexs.forEach(npkIndex => {
                        sqlParams.push([npkPath, npkIndex.name, 0])
                    })

                    task.push(true);
                }).catch(e => {
                    console.error("cache_DirPath error", e)
                    task.push(npkPath);
                });
            })
        })

        //保存dirPath
        sqlite.config.replaceInto("imagePacks2", dirPath)

        const next = (result) => {
            let success = 0;
            let failedPath = [];

            result.forEach(r => {
                if (r == true) {
                    success++;
                    return
                } else {
                    failedPath.push(r)
                    return;
                }
            })

            //批量插入数据库
            console.log("待插入数据:", sqlParams.length);
            windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                code: 1,
                text: `准备插入数据库:待插入数量${sqlParams.length}个`
            });

            //每5秒发送一次心跳
            let intv = setInterval(() => {
                let endTime = new Date();
                let diffMin = (Number(endTime.getTime()) - Number(startTime.getTime())) / 1000;
                windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                    code: 1,
                    text: `缓存建立中请稍等...(${diffMin}s)`
                });
            }, 5000);


            sqlite.npkIndex.InsertBatch(sqlParams).then(res => {
                clearInterval(intv);

                let endTime = new Date();
                let diffMin = (Number(endTime.getTime()) - Number(startTime.getTime())) / 1000;

                let text = `建立缓存完成！耗时${diffMin}秒,已建立npk缓存${success}个。总文件${files.length}个,失败文件${failedPath.length}个,失败文件:\n${failedPath.length <= 0 ? "无" : failedPath.join("\n")}`
                console.log(text);
                windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                    code: 0,
                    text
                });
                cache_lock = false;

            }).catch(err => {
                clearInterval(intv);
                console.error("批量插入数据库失败")
                console.error(err);
                windows.main.webContents.send("npk-reply", "cache_dirPath", token, {
                    code: 0,
                    text: `插入数据库失败！${err.toStirng()}`
                });
                cache_lock = false;
            })
        }
    },

    //根据img全文路径查找npk
    //返回有关信息 npk路径，包含img(关键字高亮)
    cache_findImgByPath: (token, imgPath) => {

    },

    //根据img名字查找npk
    //返回有关信息 npk路径，包含img(关键字高亮)
    cache_findImgByName: (token, imgName) => {

    },

    //根据imgPath和index加载png
    //用于图标等预览， 可能跟补丁冲突， 根据npkPath排序
    cache_loadPng: (token, imgPath, index) => {

    },

    //根据npk路径和img路径，加载全部png
    //用于预览img路径
    cache_loadNpkImgAll: (token, npkPath, imgPath) => {

    },
}

init();
initIpcMain();
module.exports = Npk;
